﻿using System;
using System.Text;
using System.Text.RegularExpressions;
using FFmpegVideoClip.Configuration;
using FFmpegVideoClip.Lib;
using FFmpegVideoClip.Lib.Processing;
using UtilityToolsCollect.ObjectsLibrary.ProcessManage;
using UtilityToolsCollect.ObjectsLibrary.TaskFlowProcessor;

namespace FFmpegVideoClip.Processing
{
    public class LosslessSplitTask : TaskProcessor, ITaskInfo
    {
        public const string RMProcessor = "rmeditor.exe";
        public const string FFProcessor = "ffmpeg.exe";
        public TimeSpan ProcessorTime { get;  set; }
        public bool IsError { get;  set; } = true;

        private string m_Arguments;
        private string ProcessorName;
        public TimeSpan FragmentTimeDuration;
        private bool IsRm = false;
        StringBuilder Info = new();
        public LosslessSplitTask(Fragment fragment,bool EnableKeyframe)
        {
            SourceData = fragment;
            ProcessorName = fragment.InputFileExtension.StartsWith(".rm", StringComparison.OrdinalIgnoreCase) ? RMProcessor : FFProcessor;
            FragmentTimeDuration = fragment.FragmentDuration;

            bool IsEnableStartTime = Tools.GetStringTimeToTimeSpan(fragment.StartTimeValue) != TimeSpan.Zero;

            if (ProcessorName == FFProcessor)
            {
                if (EnableKeyframe)
                {
                    if (IsEnableStartTime)
                        m_Arguments = $"-ss {fragment.StartTimeValue} -to {fragment.EndTimeValue} -i \"{fragment.InputPath}\" -c copy \"{fragment.TempWritePath}\" -y";
                    else
                        m_Arguments = $"-t {fragment.EndTimeValue} -i \"{fragment.InputPath}\" -c copy \"{fragment.TempWritePath}\" -y";
                }
                else
                {
                    if (IsEnableStartTime)
                        m_Arguments = $"-i \"{fragment.InputPath}\" -ss {fragment.StartTimeValue} -to {fragment.EndTimeValue} -c copy \"{fragment.TempWritePath}\" -y";
                    else
                        m_Arguments = $"-i \"{fragment.InputPath}\"  -t {fragment.EndTimeValue} -c copy \"{fragment.TempWritePath}\" -y";
                }
            }
            else
            {
                if (IsEnableStartTime)
                    m_Arguments = $"-i \"{fragment.InputPath}\" -s {fragment.StartTimeValue} -e {fragment.EndTimeValue} -o \"{fragment.TempWritePath}\"";
                else
                    m_Arguments = $"-i \"{fragment.InputPath}\" -e {fragment.EndTimeValue} -o \"{fragment.TempWritePath}\"";
                IsRm = true;
            }
        }

        public override void Execute()
        {
            Info.AppendLine($"[分割]:{ProcessorName} {m_Arguments}");
            try
            {
                ProcessShell.ProcessExecuteWaitForExit(ProcessorName, m_Arguments, SetTaskInfo, SetTaskInfo);
            }
            catch(Exception exc)
            {
                throw new LosslessSplitTaskException($"分割异常:[{Info.ToString()}]", exc);
            }
            LogManage.WriteLineNewInfo(Info.ToString());
            Info.Clear();
            Info = null!;
        }

        void SetTaskInfo(string? value)
        {
            if (string.IsNullOrWhiteSpace(value))
                return;
            Info.AppendLine(value);
            if (IsRm)
            {
                if (value.StartsWith("Processing file ("))
                {
                    ProcessorTime = int.Parse(Regex.Match(value, @"(?i)(?<=Processing file \()\d+").Value) / 100d * FragmentTimeDuration;
                }

                if (value.Contains("Processing complete!"))
                {
                    IsError = false;
                }
            }
            else
            {
                if (value.StartsWith("frame="))
                {
                    if (TimeSpan.TryParse(Regex.Match(value, @"(?i)(?<=time=)\S+").Value, out TimeSpan time))
                        ProcessorTime = time;
                }
                if (Config.FFmpegSuccessValidated.IsMatch(value))
                {
                    IsError = false;
                }
            }
        }

        [Serializable]
        public class LosslessSplitTaskException : Exception
        {
            public LosslessSplitTaskException() { }
            public LosslessSplitTaskException(string message) : base(message) { }
            public LosslessSplitTaskException(string message, Exception inner) : base(message, inner) { }
            [Obsolete]protected LosslessSplitTaskException(
              System.Runtime.Serialization.SerializationInfo info,
              System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
        }
    }
}
